package cn.kgc.springscloud.controller;

import com.netflix.loadbalancer.IRule;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.net.URI;
import java.util.Arrays;
import java.util.List;
import java.util.Random;

/**
 * @author 课工场
 * @date 2023/10/9
 * @description 服务间的通信
 * spring框架中已经封装了一个类 RestTemplate  里面包含了实现http通信的api
 * Student  =>Score
 * score  http://localhost:8504/score/m1    高      多
 * score  http://localhost:8505/score/m1    中
 * score  http://localhost:8506/score/m1    低      少
 *
 * 服务器的性能可能不一致
 *
 * 解决方案：
 * 1.定义方法 返回随机的主机节点
 *
 * 不足:
 * 1. 节点的健康状态无法控制
 * 2. 获取通信节点的策略单一  权重
 */
@RestController
@RequestMapping("student")
public class StudentController {

    @Autowired
    private DiscoveryClient discoveryClient;

    @Autowired
    private LoadBalancerClient  loadBalancerClient;


    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping("m1")
    public String method1() {
        //  获取RestTemplate 实例 实现http请求的发送    score  http://localhost:8504/score/m1
        RestTemplate restTemplate = new RestTemplate();
        // 参数1  请求接口的地址   参数2  接口响应结果的数据类型  json
        String result = restTemplate.getForObject("http://" + getHost() + "/score/m1", String.class);
        return "studentService OK  ==> scoreService : " + result;
    }


    //  RestTemplate+Ribbon 实现服务间通信
    @RequestMapping("m2")
    public String method2(){

        RestTemplate restTemplate = new RestTemplate();

        // 通过ribbon负载均衡组件拉取通信节点
        List<ServiceInstance> scoreservice = discoveryClient.getInstances("SCORESERVICE");
        //自定义策略实现节点的选择
        int index = new Random().nextInt(scoreservice.size());
        ServiceInstance serviceInstance = scoreservice.get(index);

        // 获取实例的通信地址和端口号
        URI uri = serviceInstance.getUri();

        System.out.println("uri = " + uri);

        String result = restTemplate.getForObject(uri + "/score/m1", String.class);

        return "studentService OK  ==> scoreService : " +result;
    }


    @RequestMapping("m3")
    public String method3(){

        RestTemplate restTemplate = new RestTemplate();

        // 从consul注册中心拉取通信节点    默认策略   轮循
        ServiceInstance scoreservice = loadBalancerClient.choose("SCORESERVICE");
        URI uri = scoreservice.getUri();
        String result = restTemplate.getForObject(uri + "/score/m1", String.class);
        return "studentService OK  ==> scoreService : "+result;
    }



    @RequestMapping("m4")
    public String method4(){

        //  该方式解决了服务间通信和负载均衡问题，但是代码难维护    服务间调用时路径存在强耦合关系
        String result = restTemplate.getForObject("http://SCORESERVICE/score/m1", String.class);

        return "studentService OK  ==> scoreService : "+result;
    }



    // 获取一个随机的主机节点
    public String getHost() {

        List<String> hosts = Arrays.asList("localhost:8504", "localhost:8505", "localhost:8506");
        Random random = new Random();
        int index = random.nextInt(hosts.size());
        return hosts.get(index);

    }


}
